package com.example.rdb.handle.redis;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.example.rdb.conf.ConfigInfo;
import com.example.rdb.utils.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.*;

/**
 * @author XYC
 * @描述: TODO
 * @date 21.1.1111:38
 */
@Component
@Slf4j
public class RedisMoveOne {

    @Autowired
    @Qualifier(value = "defaultRedisTemplate")
    private RedisTemplate<String, Object> defaultTemplate;//读取

    @Autowired
    @Qualifier(value = "cacheRedisTemplate")
    private RedisTemplate<String, Object> targetTemplate;//写入

    public void delete() {
        System.out.println("------REDIS-DELETE-START------");
        Set<String> keys = targetTemplate.keys(ConfigInfo.tenantWrite+":"+ConfigInfo.appWrite+":*");
        targetTemplate.delete(keys);
        System.out.println("------REDIS-DELETE-END------");
    }
    public void createJson() throws Exception {
        System.out.println("------REDIS-CREATE-JSON-START------");
        Map<String, Object> map = new HashMap<>();
        Set<String> keys = defaultTemplate.keys(ConfigInfo.tenantRead+":"+ConfigInfo.appRead+":*");
        keys.forEach(key ->{
            DataType type = defaultTemplate.type(key);
            switch (type) {
                case LIST:
                    List<Object> list = defaultTemplate.opsForList().range(key, 0, -1);
                    map.put(key,list);
                    break;
                case HASH:
                    Map<Object, Object> hash = defaultTemplate.opsForHash().entries(key);
                    map.put(key,hash);
                    break;
                case STRING:
                    Object object = defaultTemplate.opsForValue().get(key);
                    map.put(key,object);
                    break;
                case NONE:
                    System.out.println(key + ": 读取失败");
                    break;
            }
        });

        JSONObject jsonObject = JSONUtil.parseObj(map);
        OutputStreamWriter out = null;
        try {
            out = new OutputStreamWriter(new FileOutputStream("redis.json"),"utf-8");
            out.write(jsonObject.toString());
            out.flush();//清空缓冲区，强制输出数据
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            out.close();//关闭输出流
        }
        System.out.println("------REDIS-CREATE-JSON-END------");
    }

    public void redisMove() {
        System.out.println("------REDIS-START------");
        Set<String> keys = defaultTemplate.keys(ConfigInfo.tenantRead+":"+ConfigInfo.appRead+":*");
        keys.forEach(key -> {
            DataType type = defaultTemplate.type(key);
            switch (type) {
                case LIST:
                    listKey(key);
                    break;
                case HASH:
                    hashKey(key);
                    break;
                case STRING:
                    stringKey(key);
                    break;
                case NONE:
                    System.out.println(key + ": 读取失败");
                    break;
            }
        });
        //广告和组件租户和应用字段处理处理
        updateValueList(":AdPool:list");
        updateValueList(":Subassembly:list");
        //删除秘钥和版本信息
        targetTemplate.delete(ConfigInfo.tenantWrite+":"+ConfigInfo.appWrite +":secret");
        Set<String> version = targetTemplate.keys(ConfigInfo.tenantWrite+":"+ConfigInfo.appWrite +":version:*");
        targetTemplate.delete(version);
        System.out.println("------REDIS-SUCCESS------");
    }

    public void redisMoveByJson() {
        System.out.println("------REDIS-START------");
        //redis-map: *:name；*:capture:ftids；*:list(元素为json)；
        //redis-list: *:list(元素为非json);*:offline:history:*；
        //redis-stringtest: 其他
        String jsonStr = JsonUtils.readJsonFile(new File("redis.json")).replace("null","\"\"");
        JSONObject jsonObject = JSONUtil.parseObj(jsonStr);
        Map<String , Object> mapJson = jsonObject;
        mapJson.forEach((k,v) -> {
//            System.out.println("key:"+k);
            String type = JsonUtils.getType(v);
//            System.out.println("type:"+type);
            String newKey = changeKey(k);
            switch (type) {
                case "JSONArray":
                    List<Object> list = (List<Object>) v;
                    if (null != list && list.size()>0) {
                        Object o = list.get(0);
                        if("JSONObject".equals(JsonUtils.getType(o)) && !k.contains("offline:history")){//redis-stringtest
                            targetTemplate.opsForValue().set(newKey, list);

                        }else {//redis-list
                            targetTemplate.opsForList().rightPushAll(newKey, list);

                        }

                    }
                    break;
                case "JSONObject":
                    Map<Object, Object> map = (Map<Object, Object>) v;
                    if (null != map && map.size() >0 ) {//redis-hash(map)
                        if(k.contains(":name") || k.contains(":list") || k.contains("capture:ftids")){
                            targetTemplate.opsForHash().putAll(newKey, map);
                        }else {//redis-stringtest
                            targetTemplate.opsForValue().set(newKey, map);
                        }

                    }
                    break;
                default:
                    Object value = v;
                    if (null != value) {//redis-stringtest
                        targetTemplate.opsForValue().set(newKey, value);
                    }

            }
        });
        //广告和组件租户和应用字段处理
        updateValueList(":AdPool:list");
        updateValueList(":Subassembly:list");
        //删除秘钥和版本信息
        targetTemplate.delete(ConfigInfo.tenantWrite+":"+ConfigInfo.appWrite +":secret");
        Set<String> version = targetTemplate.keys(ConfigInfo.tenantWrite+":"+ConfigInfo.appWrite +":version:*");
        targetTemplate.delete(version);
        System.out.println("------REDIS-END------");
    }

    public void stringKey(String key) {
        String newKey = changeKey(key);
        Object value = defaultTemplate.opsForValue().get(key);
        if (null != value) {
            targetTemplate.opsForValue().set(newKey, value);
        }
    }

    public void hashKey(String key) {
        String newKey = changeKey(key);
        Map<Object, Object> values = defaultTemplate.opsForHash().entries(key);
        if (null != values) {
            targetTemplate.opsForHash().putAll(newKey, values);
        }
    }

    public void listKey(String key) {
        String newKey = changeKey(key);
        List<Object> values = defaultTemplate.opsForList().range(key, 0, -1);
        if (null != values && values.size()>0) {
            targetTemplate.opsForList().rightPushAll(newKey, values);
        }
    }

    public String changeKey(String key){
        String[] split = key.split(":");
        split[0] = ConfigInfo.tenantWrite;
        split[1] = ConfigInfo.appWrite;
        return String.join(":", split);
    }


    public Map updateValueList(String suffix) {
        Map map = (Map) targetTemplate.opsForHash().entries(ConfigInfo.tenantWrite+":"+ConfigInfo.appWrite + suffix);
        Set set = map.keySet();
        Map newmap = new HashMap();
        for (Object key : set) {
            String newKey = changeKey(String.valueOf(key));
            newmap.put(newKey,map.get(key));
        }
        targetTemplate.delete(ConfigInfo.tenantWrite+":"+ConfigInfo.appWrite + suffix);
        targetTemplate.opsForHash().putAll(ConfigInfo.tenantWrite+":"+ConfigInfo.appWrite + suffix,newmap);
        return newmap;
    }


}
